package com.example.auth.interceptor;

import com.example.auth.annotation.RequireRole;
import com.example.auth.entity.User;
import com.example.auth.service.UserService;
import com.example.auth.util.JwtUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Arrays;

@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // If it's not mapping to a method, proceed directly
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) handler;
        RequireRole requireRole = handlerMethod.getMethodAnnotation(RequireRole.class);

        // If there is no RequireRole annotation, proceed directly
        if (requireRole == null) {
            return true;
        }

        // Get the required roles
        String[] requiredRoles = requireRole.value();

        // Log the request path and required roles
        System.out.println("Request intercepted: " + request.getRequestURI() + ", Required roles: " + Arrays.toString(requiredRoles));

        // Get the token
        String token = request.getHeader("Authorization");
        if (token == null || !token.startsWith("Bearer ")) {
            System.out.println("Authentication failed: Token is empty or has incorrect format");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        token = token.substring(7);
        System.out.println("Token: " + token.substring(0, Math.min(10, token.length())) + "...");

        // Validate the token
        if (!jwtUtil.validateToken(token)) {
            System.out.println("Authentication failed: Token is invalid");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // Get user information
        String username = jwtUtil.getUsernameFromToken(token);
        User user = userService.findByUsername(username);
        if (user == null) {
            System.out.println("Authentication failed: User does not exist - " + username);
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // Check user status
        if ("inactive".equals(user.getStatus())) {
            System.out.println("Authentication failed: User is disabled - " + username);
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }

        System.out.println("User: " + username + ", Roles: " + user.getRoles());

        // Check if user has any of the required roles
        boolean hasRole = false;

        // Direct simple string comparison for each required role
        for (String requiredRole : requiredRoles) {
            for (var role : user.getRoles()) {
                String roleName = role.getName();
                System.out.println("Comparing role: " + roleName + " vs Required: " + requiredRole);

                // Case-insensitive comparison
                if (roleName.equalsIgnoreCase(requiredRole)) {
                    hasRole = true;
                    break;
                }

                // Always allow ADMIN access to any endpoint
                if (roleName.equalsIgnoreCase("ADMIN")) {
                    System.out.println("User has ADMIN role which has access to all endpoints");
                    hasRole = true;
                    break;
                }
                // Role hierarchy: SUPERVISOR has USER permissions
                else if (roleName.equalsIgnoreCase("SUPERVISOR") && requiredRole.equalsIgnoreCase("USER")) {
                    // Supervisor has user permissions
                    hasRole = true;
                    break;
                }
            }
            
            if (hasRole) {
                break; // If any role matches, no need to check others
            }
        }

        if (!hasRole) {
            System.out.println("Authentication failed: Insufficient permissions, missing any of the required roles - " + Arrays.toString(requiredRoles));
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }

        System.out.println("Authentication successful: User " + username + " has one of the required roles " + Arrays.toString(requiredRoles));
        return true;
    }
}